package com.brillilab.service.logic.space;

import com.brillilab.common.constant.ResultEnum;
import com.brillilab.common.exceptions.BrillilabException;
import com.brillilab.domain.enums.space.DeviceType;
import com.brillilab.domain.enums.space.SpaceTypeEnum;
import com.brillilab.domain.po.lab.Lab;
import com.brillilab.domain.po.space.Device;
import com.brillilab.domain.po.space.Panel;
import com.brillilab.domain.po.space.Room;
import com.brillilab.domain.vo.common.KeyValue;
import com.brillilab.domain.vo.print.DevicePrintVo;
import com.brillilab.domain.vo.space.DeviceAddSuccessVo;
import com.brillilab.domain.vo.space.DeviceVo;
import com.brillilab.domain.vo.space.DeviceWithPanelsVo;
import com.brillilab.domain.vo.space.RoomWithDeviceList;
import com.brillilab.domain.vo.user.UserInfoVo;
import com.brillilab.service.core.inventory.IReagentInventoryService;
import com.brillilab.service.core.lab.ILabDeviceService;
import com.brillilab.service.core.lab.ILabService;
import com.brillilab.service.core.space.*;
import com.brillilab.service.core.system.IDictService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author wuzhiyu
 * @Title: DeviceLogic
 * @ProjectName brill_lab
 * @Description: TODO
 * @date 2018/11/1419:02
 */
@Service
@Transactional
public class DeviceLogic {
    @Resource
    private IPanelService panelService;
    @Resource
    private IDeviceService deviceService;
    @Resource
    private IRoomService roomService;
    @Resource
    private IBoxService boxService;
    @Resource
    private IReagentInventoryService reagentInventoryService;
    @Resource
    private IDictService dictService;
    @Resource
    private IKitBoxService kitBoxService;
    @Resource
    private ILabDeviceService labDeviceService;
    @Resource
    private ILabService labService;

    /**
     * @return java.lang.Long
     * @Description: 新增设备，及初始化设备
     * @Params: [deviceList, labId]
     * @author wuzhiyu
     * @date 2018/11/15 9:25
     */
    @Transactional
    public DeviceAddSuccessVo add(List<DeviceWithPanelsVo> deviceList, Long labId) {
        DeviceAddSuccessVo success = new DeviceAddSuccessVo();
        Room room = roomService.get(deviceList.get(0).getDevice().getRoomId());
        Long groupId = deviceService.getNewGroupId();
        List<Long> idList = new ArrayList<>();
        success.setDeviceIdList(idList);
        success.setGroupId(groupId);
        deviceList.forEach(o -> {
            Device device = o.getDevice();
            device.setRoomId(room.getId());
            device.setLabId(labId);
            device.setDeviceType(DeviceType.DEVICE.getCode());
            device.setGroupId(groupId);
            device.setIsDelete(0);
            device.setRoomName(room.getName());
            deviceService.add(device);
            idList.add(device.getId());
            o.getPanelList().forEach(p -> {
                p.setDeviceId(device.getId());
                p.setDeviceIndex(device.getDeviceIndex());
                p.setIsDelete(0);
                p.setLabId(labId);
                p.setRoomId(room.getId());
                p.setRoomName(room.getName());
                //p.setUserReagentTypes();  todo device panell  有没有继承
                p.setZone(device.getZone());
            });
        });
        deviceList.forEach(o -> {
            List<Panel> panelList = o.getPanelList();
            panelService.addList(panelList);
        });
        return success;
    }

    /**
     * @return boolean
     * @Description: delete device and panels and boxes  in same device,if device have any inventory ,it can not be deleted
     * @Params: [deviceId]
     * @author wuzhiyu
     * @date 2018/11/15 9:30
     */
    public boolean delete(Device device) {

        List<Device> deviceGroup = deviceService.listDeviceGroupId(device.getGroupId());
        if (!CollectionUtils.isEmpty(deviceGroup)) {
            for (Device d : deviceGroup) {
                if (reagentInventoryService.InventoryCountInSpace(device.getId(), SpaceTypeEnum.DEVICE) > 0) {
                    throw new BrillilabException(ResultEnum.DATA_EXIST_CANT_DELETE);
                }
                deviceService.delete(d.getId());
                panelService.delete(d.getId(), SpaceTypeEnum.DEVICE);
                boxService.delete(d.getId(), SpaceTypeEnum.DEVICE);
                kitBoxService.delete(d.getId(), SpaceTypeEnum.DEVICE);
                panelService.deletePanelGridUsedByDeviceId(d.getId());
            }
        } else {
            if (reagentInventoryService.InventoryCountInSpace(device.getId(), SpaceTypeEnum.DEVICE) > 0) {
                throw new BrillilabException(ResultEnum.DATA_EXIST_CANT_DELETE);
            }
            deviceService.delete(device.getId());
        }
        return true;
    }

    public RoomWithDeviceList deviceGroupList(Room room) {
        RoomWithDeviceList result = new RoomWithDeviceList();
        result.setRoom(room);
        List<List<DeviceVo>> deviceData = new ArrayList<>();
        result.setDeviceList(deviceData);
        Map<Integer, String> zoneMap = dictService.getZoneMap();
        List<Device> deviceList = deviceService.list(room.getId());
        if (CollectionUtils.isEmpty(deviceList)) {
            List<DeviceVo> groupList = new ArrayList<>();
            deviceData.add(groupList);
        } else {
            List<DeviceVo> notDeviceList = deviceList.stream().filter(o -> o.getGroupId() == null).map(o -> {
                DeviceVo dv = new DeviceVo();
                BeanUtils.copyProperties(o, dv);
                return dv;
            }).collect(Collectors.toList());
            notDeviceList.forEach(d -> {
                List<DeviceVo> vol = new ArrayList<>();
                vol.add(d);
                deviceData.add(vol);
            });
            List<Long> idList = deviceList.stream().filter(o -> o.getGroupId() != null).map(Device::getGroupId).distinct().collect(Collectors.toList());
            idList.forEach(i -> {
                List<DeviceVo> list = deviceList.stream().filter(d -> d.getGroupId() != null && d.getGroupId().equals(i)).map(d -> {
                    DeviceVo dv = new DeviceVo();
                    BeanUtils.copyProperties(d, dv);
                    if (d.getDeviceType().equals(DeviceType.DEVICE.getCode())) {
                        dv.setZoneName(zoneMap.get(d.getZone()));
                    }
                    return dv;
                }).collect(Collectors.toList());
                deviceData.add(list);
            });
        }
        return result;
    }

    public boolean updateAio(Device device, String name) {
        Device deviceUpdate = new Device();
        deviceUpdate.setId(device.getId());
        deviceUpdate.setRemark(name);
        deviceService.update(deviceUpdate);
        labDeviceService.updateDeviceName(device.getAioDeviceId(), name);
        return true;
    }

    public List<KeyValue<String, List<DevicePrintVo>>> getPrintList(Long labId) {
        List<Device> deviceList = deviceService.getLabAllDeviceList(labId, null);
        List<KeyValue<String, List<DevicePrintVo>>> list = new ArrayList<>();
        List<Room> roomList = deviceList.stream().map(d -> {
            Room room = new Room();
            room.setId(d.getRoomId());
            room.setName(d.getRoomName());
            return room;
        }).distinct().collect(Collectors.toList());
        Map<Integer, String> zoneMap = dictService.getZoneMap();
        Lab lab = labService.selectById(labId);
        roomList.forEach(r -> {
            KeyValue<String, List<DevicePrintVo>> kv = new KeyValue<>();
            list.add(kv);
            kv.setKey(r.getName());
            List<DevicePrintVo> printVoList = deviceList.stream().filter(d -> d.getRoomId().equals(r.getId())).map(d -> {
                DevicePrintVo vo = new DevicePrintVo();
                vo.setDeviceId(d.getId());
                vo.setZoneName(zoneMap.get(d.getZone()));
                vo.setDeviceIndex(d.getDeviceIndex());
                vo.setLabName(lab.getName() + "[" + zoneMap.get(d.getZone()) + "]");
                vo.setBarCode("labinone://inventoryQuery?deviceId=" + d.getId());
                return vo;
            }).collect(Collectors.toList());
            kv.setValue(printVoList);
        });
        return list;
    }

    public DevicePrintVo getPrint(UserInfoVo user, Long deviceId) {
        Device device = deviceService.get(deviceId);
        Assert.notNull(device, "数据不存在");
        Assert.isTrue(device.getLabId().equals(user.getLabId()), "数据不存在");
        Map<Integer, String> zoneMap = dictService.getZoneMap();
        DevicePrintVo vo = new DevicePrintVo();
        Lab lab = labService.selectById(device.getLabId());
        vo.setDeviceId(device.getId());
        vo.setZoneName(zoneMap.get(device.getZone()));
        vo.setDeviceIndex(device.getDeviceIndex());
        vo.setLabName(lab.getName() + "[" + zoneMap.get(device.getZone()) + "]");
        vo.setBarCode("labinone://inventoryQuery?deviceId=" + device.getId());
        return vo;
    }
}
